package main.algorithms.aco;

import java.util.ArrayList;

import main.problemstruktur.Knoten;

public class Ant {
	private int bereich;
	private int zeit;
	private final Double[] heuristics;
	private final ArrayList<Knoten> solution;
	private final ArrayList<Boolean> visited;
	private boolean isFinished = false;
	private final ACOProblem problem;

	public Ant(ACOProblem problem) {
		bereich = 0;
		zeit = 0;
		heuristics = new Double[problem.getNodes().size()];
		this.problem = problem;
		solution = new ArrayList<Knoten>();
		for (int i = 0; i < problem.getNodes().size(); i++) {
			solution.add(null);
		}
		visited = new ArrayList<Boolean>();
		for (int i = 0; i < problem.getNodes().size(); i++) {
			visited.add(false);
		}
	}

	public void updateHeuristics() {
		while (true) {
			boolean nodeGefunden = false;
			for (Knoten node : problem.getNodes()) {
				int id = node.getId();
				if (!visited.get(id)) {
					int cost = node.getTimeToIntervall(bereich, zeit);
					if (cost != -1) {
						nodeGefunden = true;
						heuristics[id] = calculateHeuristicFromValue(cost);
					} else
						heuristics[id] = 0.0;
				} else
					heuristics[id] = 0.0;
			}
			if (nodeGefunden)
				return;
			bereich++;
			if (problem.getAnzahlBereiche() <= bereich) {
				setIsFinished(true);
				return;
			}
		}
	}

	private void setIsFinished(boolean b) {
		isFinished = b;
	}

	private Double calculateHeuristicFromValue(int cost) {
		return 1.0 / (cost + 1);
	}

	public boolean isFinished() {
		return isFinished;
	}

	public boolean getVisited(int id) {
		return visited.get(id);
	}

	public boolean setVisited(int id) {
		return visited.set(id, true);
	}

	public Knoten getTourInstanze(int position) {
		return solution.get(position);
	}

	public Double getHeuristicalValue(int nodeID) {
		return heuristics[nodeID];
	}

	public int getMissingMemberCount() {
		int result = 0;

		for (int i = 0; i < problem.getNodes().size(); i++) {
			if (solution.get(i) == null)
				result++;
		}
		return result;
	}

	public Double getCost() {
		return 1 / (getMissingMemberCount() + 1.0);
	}

	public void setTourInstanze(int step, int choice) {
		Knoten node=problem.getNodes().get(choice);
		solution.set(step, node);
		zeit=zeit+node.getTimeToIntervall(bereich, zeit)+node.getDauer();
		setVisited(choice);
	}
}
